package utils

import (
	"fmt"
	"sync"
)

/***
 * 循环使用列表
 *    当超过最大队列是会移除第一个
 */
type SyncCycleList struct {
	lock          sync.RWMutex
	dlist         *DLinklist
	max_size      int32
	OnRemoveEvent func(args ...interface{})
}

func NewSyncCycleList() *SyncCycleList {
	rval := &SyncCycleList{dlist: NewDlinklist(), max_size: 1024}
	return rval
}

func (this *SyncCycleList) Count() int32 {
	return this.dlist.cnt
}

func (this *SyncCycleList) ConfigMaxSize(val int32) *SyncCycleList {
	this.max_size = val
	return this
}

func (this *SyncCycleList) checkTrim() {
	if this.max_size <= 0 {
		return
	}
	for this.dlist.cnt > this.max_size {
		ok, _ := this.RemoveFirst()
		if !ok {
			break
		}
	}
}

func (this *SyncCycleList) LogMsg(s string, args ...interface{}) {
	str := fmt.Sprintf(s, args...)
	this.Push(fmt.Sprintf("[%s]%s", NowString(), str))
}

func (this *SyncCycleList) Push(args ...interface{}) {
	node := NewDlinknodeFromPool()
	node.Value = args
	this.lock.Lock()
	this.dlist.Append(node)
	this.lock.Unlock()
	this.checkTrim()
}

/*
**

	如果PeekFirst() 处理成功移除(RemoveFirst), 要确保该操作只有一个线程进入
*/
func (this *SyncCycleList) PeekFirst() (ok bool, val interface{}) {
	this.lock.RLock()
	defer this.lock.RUnlock()
	node := this.dlist.First()
	if node == nil {
		return false, nil
	}
	return true, node.Value
}

func (this *SyncCycleList) RemoveFirst() (ok bool, val interface{}) {
	this.lock.Lock()
	node := this.dlist.RemoveFirst()
	this.lock.Unlock()
	if node != nil {
		val := node.Value
		node.release2Pool()
		if this.OnRemoveEvent != nil {
			if vals, ok := val.([]interface{}); ok {
				this.OnRemoveEvent(vals...)
			} else {
				this.OnRemoveEvent(vals)
			}
		}
		return true, val
	} else {
		return false, nil
	}
}

func (this *SyncCycleList) RangeDesc(cb func(args ...interface{}) bool) int {

	this.lock.RLock()
	lst := this.dlist.List()
	this.lock.RUnlock()
	if len(lst) == 0 {
		return 0
	}
	n := 0
	for i := len(lst) - 1; i >= 0; i-- {
		val := lst[i]
		n++
		if vals, ok := val.([]interface{}); ok {
			if !cb(vals...) {
				return n
			}
		} else {
			if !cb(val) {
				return n
			}
		}
	}

	return n
}

func (this *SyncCycleList) Range(cb func(args ...interface{}) bool) int {

	this.lock.RLock()
	lst := this.dlist.List()
	this.lock.RUnlock()
	if len(lst) == 0 {
		return 0
	}
	n := 0
	for i := 0; i < len(lst); i++ {
		val := lst[i]
		n++
		if vals, ok := val.([]interface{}); ok {
			if !cb(vals...) {
				return n
			}
		} else {
			if !cb(val) {
				return n
			}
		}
	}

	return n
}

func (this *SyncCycleList) Clear() int {
	i := 0
	for {
		ok, _ := this.RemoveFirst()
		if !ok {
			break
		}
		i++
	}

	return i
}
